/*
  File:    GhostFluidMethod.h
  Purpose: Advanced method for solving discontinuous Poisson problem
           on irregular domains. Second-order accuracy with brand-new
           discretization of [grad(u).n] = 0. Solves the following problem

           0 = div( DiffusionConstant grad(u) ) + SourceFunction 
		                                       + SourceFunctionU * u
           [u] = JumpCondition(x,y)
           [grad(u).n] = 0

  Contact: Paul Macklin
           pmacklin@math.uci.edu
		  http://math.uci.edu/~pmacklin
*/


double gfmUpdateBoundaryPoint( Matrix& X, Matrix& Y, Matrix& Solution,
							  double (*LeftBC)(double),   char LeftBCtype,  
							  double (*RightBC)(double),  char RightBCtype,     
							  double (*BottomBC)(double), char BottomBCtype,   
							  double (*TopBC)(double),    char TopBCtype,  
							  int i, int j );
double gfmImplicitUpdateContinuousD_MatrixForm( Matrix& X,Matrix& Y,Matrix& Phi, Matrix& Solution, 
											   Matrix& Diffusivity,
											   Matrix& SourceFunction, 
											   Matrix& SourceFunctionU, 
											   double (*JumpCondition)(double,double),
											   double (*NormalDerivativeJumpCondition)(double,double),
											   int i, int j, double dx, double dy );


Matrix GhostFluidMethod_Deprecated( Matrix &X, Matrix &Y, Matrix &Phi, 
   Matrix& DiffusionConstant, Matrix& SourceFunction, 
   Matrix& SourceFunctionU, 
   double (*LeftBC)(double),   char LeftBCtype,  
   double (*RightBC)(double),  char RightBCtype,     
   double (*BottomBC)(double), char BottomBCtype,   
   double (*TopBC)(double),    char TopBCtype,  
   double (*JumpCondition)(double,double), 
   Matrix& InitialGuess, int MaxIterations, double Tolerance );

Matrix GhostFluidMethodOld_Deprecated( Matrix &X, Matrix &Y, Matrix &Phi, 
   Matrix& DiffusionConstant, Matrix& SourceFunction, 
   Matrix& SourceFunctionU, 
   double (*LeftBC)(double),   char LeftBCtype,  
   double (*RightBC)(double),  char RightBCtype,     
   double (*BottomBC)(double), char BottomBCtype,   
   double (*TopBC)(double),    char TopBCtype,  
   double (*JumpCondition)(double,double), 
   Matrix& InitialGuess, int MaxIterations, double Tolerance );

Matrix GhostFluidMethodNew_Deprecated( Matrix &X, Matrix &Y, Matrix &Phi, 
   Matrix& DiffusionConstant, Matrix& SourceFunction, 
   Matrix& SourceFunctionU, 
   double (*LeftBC)(double),   char LeftBCtype,  
   double (*RightBC)(double),  char RightBCtype,     
   double (*BottomBC)(double), char BottomBCtype,   
   double (*TopBC)(double),    char TopBCtype,  
   double (*JumpCondition)(double,double), 
   double (*NormalJumpCondition)(double,double), 
   Matrix& InitialGuess, int MaxIterations, double Tolerance );

Matrix GhostFluidMethodNonAdaptive_Deprecated( Matrix &X, Matrix &Y, Matrix &Phi, 
   Matrix& DiffusionConstant, Matrix& SourceFunction, 
   Matrix& SourceFunctionU, 
   double (*LeftBC)(double),   char LeftBCtype,  
   double (*RightBC)(double),  char RightBCtype,     
   double (*BottomBC)(double), char BottomBCtype,   
   double (*TopBC)(double),    char TopBCtype,  
   double (*JumpCondition)(double,double), 
   Matrix& InitialGuess, int MaxIterations, double Tolerance );

Matrix GhostFluidMethodRandom_Deprecated( Matrix &X, Matrix &Y, Matrix &Phi, 
   Matrix& DiffusionConstant, Matrix& SourceFunction, 
   Matrix& SourceFunctionU, 
   double (*LeftBC)(double),   char LeftBCtype,  
   double (*RightBC)(double),  char RightBCtype,     
   double (*BottomBC)(double), char BottomBCtype,   
   double (*TopBC)(double),    char TopBCtype,  
   double (*JumpCondition)(double,double), 
   Matrix& InitialGuess, int MaxIterations, double Tolerance );

   
  Matrix GhostFluidMethodNew_Deprecated( Matrix &X, Matrix &Y, Matrix &Phi, 
   double (*InteriorDiffusivity)(double,double), 
   double (*ExteriorDiffusivity)(double,double),   
   Matrix& SourceFunction, Matrix& SourceFunctionU, 
   double (*LeftBC)(double),   char LeftBCtype,  
   double (*RightBC)(double),  char RightBCtype,     
   double (*BottomBC)(double), char BottomBCtype,   
   double (*TopBC)(double),    char TopBCtype,  
   double (*JumpCondition)(double,double), 
   double (*NormalJumpCondition)(double,double), 
   Matrix& InitialGuess, int MaxIterations, double Tolerance ); 
   
/* the new stuff */

Matrix GhostFluidMethod( Matrix& X, Matrix& Y, Matrix& Phi, 
   Matrix& Diffusivity, 
   Matrix& SourceFunction, Matrix& SourceFunctionU, 
   double (*LeftBC)(double),   char LeftBCtype,  
   double (*RightBC)(double),  char RightBCtype,     
   double (*BottomBC)(double), char BottomBCtype,   
   double (*TopBC)(double),    char TopBCtype,  
   double (*JumpCondition)(double,double), 
   double (*NormalJumpCondition)(double,double), 
   Matrix& InitialGuess, int MaxIterations, double Tolerance );
   
Matrix GhostFluidMethod( Matrix& X, Matrix& Y, Matrix& Phi, 
   double (*Diffusivity)(double,double), 
   Matrix& SourceFunction, Matrix& SourceFunctionU, 
   double (*LeftBC)(double),   char LeftBCtype,  
   double (*RightBC)(double),  char RightBCtype,     
   double (*BottomBC)(double), char BottomBCtype,   
   double (*TopBC)(double),    char TopBCtype,  
   double (*JumpCondition)(double,double), 
   double (*NormalJumpCondition)(double,double), 
   Matrix& InitialGuess, int MaxIterations, double Tolerance );
   
void WithOxygenGhostFluidMethod_Generic_MatrixForm(Matrix& X, Matrix& Y, Matrix& Phi, 
   Matrix& Diffusivity, 
   Matrix& SourceFunction, Matrix& SourceFunctionU, 
   double (*PLeftBC)(double),   char PLeftBCtype,  
   double (*PRightBC)(double),  char PRightBCtype,     
   double (*PBottomBC)(double), char PBottomBCtype,   
   double (*PTopBC)(double),    char PTopBCtype,  
   double (*JumpCondition)(double,double), 
   double (*NormalJumpCondition)(double,double), double PTolerance,
  /* Matrix& InitialGuess, */ 
   double (*LeftBC)(double),   char LeftBCtype,  
   double (*RightBC)(double),  char RightBCtype,     
   double (*BottomBC)(double), char BottomBCtype,   
   double (*TopBC)(double),    char TopBCtype,  
   double (*DiffusionConstant)(double,double,double,int,int), 
   double (*SourceTimesU)(double,double,double,int,int),
   double (*SourceRemainder)(double,double,double,int,int),
   int MaxIterations, double OTolerance ,
   double ImplicitUpdate(
Matrix& Solution, 
double (*Diffusion)(double,double,double,int,int),
double (*SourceTimesU)(double,double,double,int,int),
double (*SourceRemainder)(double,double,double,int,int), 
int i, int j, 
double x, double y, double dx, double dy ),
/*
double UpdateBoundaryPoint( Matrix& Solution, 
   double (*LeftBC)(double),   char LeftBCtype,  
   double (*RightBC)(double),  char RightBCtype,     
   double (*BottomBC)(double), char BottomBCtype,   
   double (*TopBC)(double),    char TopBCtype,  
   int i, int j, 
   double x, double y )*/
double UpdateBoundaryPoint(Matrix& Solution, 
double (*Diffusion)(double,double,double,int,int),
double (*SourceTimesU)(double,double,double,int,int),
double (*SourceRemainder)(double,double,double,int,int), 
int i, int j, 
double x, double y, double dx, double dy));

void WithOxygenWTGhostFluidMethod_Generic_MatrixForm(Matrix& X, Matrix& Y, Matrix& Phi, 
												   Matrix& Diffusivity, 
												   Matrix& SourceFunction, Matrix& SourceFunctionU, 
												   double (*PLeftBC)(double),   char PLeftBCtype,  
												   double (*PRightBC)(double),  char PRightBCtype,     
												   double (*PBottomBC)(double), char PBottomBCtype,   
												   double (*PTopBC)(double),    char PTopBCtype,  
												   double (*JumpCondition)(double,double), 
												   double (*NormalJumpCondition)(double,double), double PTolerance,
												   /* Matrix& InitialGuess, */ 
												   double (*LeftBC)(double),   char LeftBCtype,  
												   double (*RightBC)(double),  char RightBCtype,     
												   double (*BottomBC)(double), char BottomBCtype,   
												   double (*TopBC)(double),    char TopBCtype,  
												   double (*DiffusionConstant)(double,double,double,int,int), 
												   double (*SourceTimesU)(double,double,double,int,int),
												   double (*SourceRemainder)(double,double,double,int,int),
												   int MaxIterations, double OTolerance ,
												   double ImplicitUpdate(
																		 Matrix& Solution, 
																		 double (*Diffusion)(double,double,double,int,int),
																		 double (*SourceTimesU)(double,double,double,int,int),
																		 double (*SourceRemainder)(double,double,double,int,int), 
																		 int i, int j, 
																		 double x, double y, double dx, double dy ),
/*
 double UpdateBoundaryPoint( Matrix& Solution, 
 double (*LeftBC)(double),   char LeftBCtype,  
 double (*RightBC)(double),  char RightBCtype,     
 double (*BottomBC)(double), char BottomBCtype,   
 double (*TopBC)(double),    char TopBCtype,  
 int i, int j, 
 double x, double y )*/
												   double UpdateBoundaryPoint(Matrix& Solution, 
																			  double (*Diffusion)(double,double,double,int,int),
																			  double (*SourceTimesU)(double,double,double,int,int),
																			  double (*SourceRemainder)(double,double,double,int,int), 
																			  int i, int j, 
																			  double x, double y, double dx, double dy)
													 ,double WTolerance,
													 double AngioFluidPressureUpdate( Matrix& Diffusion,  Matrix& BloodNodePressure, Matrix& Pressure, Matrix& Solution, Matrix& CellSource, int i, int j),
													 double FluidPressureUpdateBoundaryPoint( Matrix& Diffusion,  Matrix& BloodNodePressure, Matrix& Pressure, Matrix& Solution,  int i, int j));